package seiacpjava_a2.datastructures.hashtable;

import static org.junit.Assert.*;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;

import org.junit.Test;

import seiacpjava_a2.datastructures.DataStructure;
import seiacpjava_a2.datastructures.DataStructureFactory;
import seiacpjava_a2.datastructures.linkedlist.LinkedList;
import seiacpjava_a2.utilities.FileParser;


public class HashtableTestCase {


	
	@Test
	public void testHashTable() {
					
		int [] items = new int[6];
		
		items[0] = 0 ; items[1] = 1 ; items[2] = 2;
		items[3] = 10; items[4] = 11;
		items[5] = 20;
		
		HashTableStrategy strategy = new ModuloStrategy();		
		HashTable table = new HashTable(items,strategy);
		
		assertEquals(10, table.getNumberOfBuckets());
		
		LinkedList bucket0 =table.getBucket(0);
		assertEquals(3, bucket0.getLength());
		assertTrue(bucket0.contains(0));
		assertTrue(bucket0.contains(10));
		assertTrue(bucket0.contains(20));
		assertFalse(bucket0.contains(11));
				
		LinkedList bucket1 = table.getBucket(1);
		assertEquals(2, bucket1.getLength());
		assertTrue(bucket1.contains(1));
		assertTrue(bucket1.contains(11));
		assertFalse(bucket1.contains(10));
		
		LinkedList bucket2 =table.getBucket(2);
		assertEquals(1, bucket2.getLength());
		assertTrue(bucket2.contains(2));
		assertFalse(bucket2.contains(10));
		
		LinkedList bucket3 =table.getBucket(3);
		assertEquals(0, bucket3.getLength());
		
		LinkedList bucket4 =table.getBucket(4);
		assertEquals(0, bucket4.getLength());
		
		LinkedList bucket5 =table.getBucket(5);
		assertEquals(0, bucket5.getLength());
		
		LinkedList bucket6 =table.getBucket(6);
		assertEquals(0, bucket6.getLength());
		
		LinkedList bucket7 =table.getBucket(7);
		assertEquals(0, bucket7.getLength());
		
		LinkedList bucket8 =table.getBucket(8);
		assertEquals(0, bucket3.getLength());
		
		LinkedList bucket9 =table.getBucket(9);
		assertEquals(0, bucket9.getLength());
				
	}
	
	
	@Test
	public void testContains(){
		
		int [] items = new int[6];
		
		items[0] = 0 ; items[1] = 1 ; items[2] = 2;
		items[3] = 10; items[4] = 11;
		items[5] = 20;
			
		HashTableStrategy strategy = new ModuloStrategy();		
		HashTable table = new HashTable(items,strategy);
		
		// 1st bucket
		assertTrue(table.contains(0));
		assertEquals(1,table.getNumberOfAccesses());	
		assertTrue(table.contains(10));
		assertEquals(2,table.getNumberOfAccesses());
		assertTrue(table.contains(20));
		assertEquals(3,table.getNumberOfAccesses());
		
		// 2nd bucket
		assertTrue(table.contains(1));
		assertEquals(1,table.getNumberOfAccesses());		
		assertTrue(table.contains(11));
		assertEquals(2,table.getNumberOfAccesses());
		
		// 3rd bucket
		assertTrue(table.contains(2));
		assertEquals(1,table.getNumberOfAccesses());
				
		// Negative Testing for Contains
		assertFalse(table.contains(30));
		assertEquals(3,table.getNumberOfAccesses());
		
		assertFalse(table.contains(21));
		assertEquals(2,table.getNumberOfAccesses());
		
		assertFalse(table.contains(22));
		assertEquals(1,table.getNumberOfAccesses());
		
		assertFalse(table.contains(25));
		assertEquals(0,table.getNumberOfAccesses());
		
	}
	
	@Test
	public void testHashTableWithLargeNumberOfItems(){
		
		int [] items;
		String inputFile = "C:/comp6411_files/ht_inputfile_1000Items_forUnitTesting.txt";
	//	String inputFile = "C:/comp6411_files/ht_inputfile_10Items_forUnitTesting.txt";
		
		
		
		Path inputFilePath = FileSystems.getDefault()
				.getPath(inputFile);
		
		FileParser parser = new FileParser(inputFilePath);	
		
		try {
			  items = parser.getNumbers();
			  HashTableStrategy strategy = new ModuloStrategy();		
			  HashTable table = new HashTable(items,strategy);
			  
			  assertEquals(1000, items.length);
			  assertEquals(1000, table.getSize());
				  
			
		} catch (IOException e) {
			fail();
		}
		
	}
	
	
	@Test
	public void testHashTableWithReflexiveStrategy(){
		
		int [] items;
		String inputFile = "C:/comp6411_files/ht_inputfile_1000Items_forUnitTesting.txt";	
		
		
		Path inputFilePath = FileSystems.getDefault()
				.getPath(inputFile);
		
		FileParser parser = new FileParser(inputFilePath);	
		
		try {
			  items = parser.getNumbers();
			  HashTableStrategy strategy = new ReflexiveStrategy();		
			  HashTable table = new HashTable(items,strategy);
			  
			  assertEquals(1000, items.length);
			  assertEquals(1000, table.getSize());
			  
			  for (int i =0; i< table.buckets.length;i++)
			  {
				  LinkedList bucket = table.getBucket(i);
				  assertTrue(bucket.getLength() <= 1);
			  }
				  
			
		} catch (IOException e) {
			fail();
		}
		
	}
	

}
